import copy
from PyQt5.QtWidgets import (
    QTableWidget,
    QVBoxLayout,
    QWidget,
    QSizePolicy,
    QComboBox,
    QHeaderView,
    QStyledItemDelegate,
    QTableWidgetItem,
    QLineEdit,
    QMenu,
    QApplication,
)
from PyQt5.QtCore import Signal, Qt, QEvent
from PyQt5.QtGui import (
    QPainter,
    QPen,
    QColor,
    QDoubleValidator,
    QIntValidator,
    QCursor,
    QFocusEvent,
)
from PyQt5.QtCore import QTimer
from functools import partial

# from ui_style import UiStyle
from . import message_box as MBox
from .util.type_conversion import TypeConversion
from .custom_widget import SelectBox, CustomCellComboBoxMultiSelectStr


class CustomComboBox(SelectBox):
    popupHidden = Signal(str)

    def hidePopup(self):
        super().hidePopup()  # 调用父类的 hidePopup 方法
        QTimer.singleShot(100, self.get_current_value)  # 延迟获取当前选中项

    def get_current_value(self):
        value = self.currentText()
        self.popupHidden.emit(value)  # 发出信号


class FloatValidatorDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(FloatValidatorDelegate, self).__init__(parent)
        self.validator = QDoubleValidator(self)

    def createEditor(self, parent, option, index):
        editor = QLineEdit(parent)  # 使用 QLineEdit 作为编辑器
        editor.setValidator(self.validator)
        return editor


class IntValidatorDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(IntValidatorDelegate, self).__init__(parent)
        self.validator = QIntValidator(self)

    def createEditor(self, parent, option, index):
        editor = QLineEdit(parent)  # 使用 QLineEdit 作为编辑器
        editor.setValidator(self.validator)
        return editor


class CustomTableWidgetItem(QTableWidgetItem):
    def __init__(self, text, isComplete=False):
        super().__init__(text)
        self.setTextAlignment(Qt.AlignCenter)  # 文本居中对齐
        self._completeValue = None
        self.isComplete = isComplete
        self.completeFlag = ""

    def setCompleteValue(self, value):
        self._completeValue = value

    def getCompleteValue(self):
        return self._completeValue

    def setText(self, text, CompleteValue=""):
        if self.isComplete:
            self.setCompleteValue(CompleteValue)
        super().setText(text)


# 新增行必须使用 addRow()
class CustomTable(QTableWidget):
    select_changed_signal = Signal(object)
    item_changed_signal = Signal(object)

    def __init__(
        self, rows=0, columns=2, isLibrary=False, useCustomMenu=True, parent=None
    ):
        super(CustomTable, self).__init__(parent)
        self.flag = ""
        self.isLibrary = isLibrary
        self.combo_box = None
        self.useCustomMenu = useCustomMenu
        self.isAdding = False
        self.columnReadOnly = []
        self.unEnableColunm = []
        self.rowFloat = []
        self.rowInt = []
        self.rowSelect = []
        self.rowMultiSelect = []
        self.selectOptions = {}
        self.selectMultiOptions = {}
        self.isHandleDel = False
        self.noEditHint = "该单元格不可编辑"
        self.noDelHint = "该行不可删除"
        self.hasNoEditCell = False
        self.isFirstColumnUnique = False
        self.current_edit_row = -1
        self.current_edit_col = -1
        self.setRowCount(rows)
        self.setColumnCount(columns)
        self.verticalHeader().setDefaultSectionSize(30)
        self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 不高亮标题
        self.horizontalHeader().setHighlightSections(False)
        #  # 垂直分割宽度
        self.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
        self.verticalHeader().setVisible(False)

        if self.useCustomMenu:
            self.setContextMenuPolicy(Qt.CustomContextMenu)
            # 创建QMenu信号事件
            self.customContextMenuRequested.connect(self.showMenu)
            self.contextMenu = QMenu(self)
            self.AD = self.contextMenu.addAction("新增")
            self.DL = self.contextMenu.addAction("删除")
            self.CP = self.contextMenu.addAction("复制")
            self.NT = self.contextMenu.addAction("粘贴")
            self.AD.triggered.connect(self.add)
            self.DL.triggered.connect(self.delete)
            self.CP.triggered.connect(self.copy)
            self.NT.triggered.connect(self.paste)

        self.cellDoubleClicked.connect(self.on_cell_double_clicked)
        self.cellChanged.connect(self.nameCellChange)

    def showMenu(self, pos):
        self.contextMenu.exec_(QCursor.pos())  # 在鼠标位置显示

    def keyPressEvent(self, event):  # 重写键盘监听事件
        if not self.useCustomMenu:
            super().keyPressEvent(event)
            return

        # 监听 CTRL+C 组合键，实现复制数据到粘贴板
        if (
            event.key() == Qt.Key_C
        ) and QApplication.keyboardModifiers() == Qt.ControlModifier:
            self.copy()  # 获取当前表格选中的数据
        elif (
            event.key() == Qt.Key_X
        ) and QApplication.keyboardModifiers() == Qt.ControlModifier:
            self.cut()
        elif (
            event.key() == Qt.Key_V
        ) and QApplication.keyboardModifiers() == Qt.ControlModifier:
            self.paste()
        # elif (event.key() == Qt.Key_Z) and QApplication.keyboardModifiers() == Qt.ControlModifier:
        #     self.paste()
        else:
            super().keyPressEvent(event)

    # 判断是否复制了多个单元格
    def isMutli(self, list):
        if len(list) == 0:
            return False
        if len(list) == 1:
            if len(list[0]) <= 1:
                return False
        return True

    # click event
    def add(self):
        lastRow = self.selectedLastRow()
        if lastRow < 0:
            lastRow = self.rowCount()
        else:
            lastRow = lastRow + 1
        self.addRow(lastRow)

    def delete(self):
        selected_indexes = self.selectedIndexes()
        if not selected_indexes:
            MBox.warning(
                "请选择要删除的行",
            )
            return
        if not self.isHandleDel:
            isDel = MBox.confirm(
                "是否确认删除当前选中行?",
            )
            if isDel:
                # 将索引按行号降序排序，这样我们可以从底部开始删除行
                selected_rows = sorted(
                    set(index.row() for index in selected_indexes), reverse=True
                )
                for row in selected_rows:
                    self.removeRow(row)
            return

        isNoEdit = False
        for selectRow in selected_indexes:
            item = self.item(selectRow.row(), 0)
            if not (item.flags() & Qt.ItemIsEditable):
                isNoEdit = True

        if isNoEdit:
            isDel = MBox.confirm(
                "当前选中行包含被使用的材料，该材料无法删除，是否继续?",
            )
            if isDel:
                # 将索引按行号降序排序，这样我们可以从底部开始删除行
                selected_rows = sorted(
                    set(index.row() for index in selected_indexes), reverse=True
                )
                for row in selected_rows:
                    item = self.item(row, 0)
                    if item.flags() & Qt.ItemIsEditable:
                        self.removeRow(row)
        else:
            isDel = MBox.confirm(
                "是否确认删除当前选中行?",
            )
            if isDel:
                # 将索引按行号降序排序，这样我们可以从底部开始删除行
                selected_rows = sorted(
                    set(index.row() for index in selected_indexes), reverse=True
                )
                for row in selected_rows:
                    self.removeRow(row)

    def paste(self):
        self.paste_tb_text()

    def copy(self):
        text = self.selected_tb_text()  # 获取当前表格选中的数据
        if text:
            clipboard = QApplication.clipboard()
            clipboard.setText(text)

    def cut(self):
        self.copy()
        self.del_tb_text()

    def nameCellChange(self, row, col):
        if not self.isFirstColumnUnique:
            return
        if self.current_edit_row == -1 or self.current_edit_col == -1:
            return
        if col != 0:
            return
        if row == self.current_edit_row and col == self.current_edit_col:
            item = self.item(row, col)
            self.value_is_duplicate(curItem=item)
            self.current_edit_row = -1
            self.current_edit_col = -1

    # click event patch
    def del_tb_text(self):
        try:
            indexes = self.selectedIndexes()
            for index in indexes:
                row, column = index.row(), index.column()
                item = CustomTableWidgetItem()
                self.setItem(row, column, item)
        except BaseException as e:
            print(e)
            return

    def paste_tb_text(self):
        try:
            text = QApplication.clipboard().text()
            ls = text.split("\n")
            ls = [item for item in ls if item and item.strip()]
            ls1 = []
            for row in ls:
                ls1.append(row.split("\t"))
            rows = len(ls)
            isMutli = self.isMutli(ls1)
            indexes = self.selectedIndexes()
            if indexes:
                # 选中单元后粘贴
                if isMutli:
                    # 粘贴多个
                    for index in indexes:
                        index = index
                        break
                    r, c = index.row(), index.column()  # 拿到选中的第一个单元格
                    if self.isFirstColumnUnique:
                        # 粘贴从第一列开始
                        if c == 0:
                            copyData = ls1.copy()
                            tableDict = self.getTableDict()
                            for addIndex in range(
                                len(copyData) - 1, -1, -1
                            ):  # 倒序遍历
                                csvRow = copyData[addIndex]
                                if (
                                    csvRow[0] is not None
                                    and str(csvRow[0]) in tableDict
                                ):
                                    self.updateRowData(
                                        tableDict[str(csvRow[0])]["row"], csvRow
                                    )
                                    del ls1[addIndex]
                            self.addMulitRows(ls1, isResizeRows=True)
                        else:
                            # 粘贴不从第一列开始
                            for addRow in range(rows):
                                # 拿到真实的row
                                row = addRow + r
                                if row > self.rowCount() - 1:
                                    # 新增行
                                    rowData = [None] * self.columnCount()
                                    rowData[c : c + len(ls1[addRow])] = ls1[addRow]
                                    self.addRow(row, rowData)
                                else:
                                    # 修改行
                                    rowData = self.getRowData(row)
                                    rowData[c : c + len(ls1[addRow])] = ls1[addRow]
                                    self.fillRowData(row, rowData)
                    else:
                        # 第一列的值不唯一
                        for addRow in range(rows):
                            # 拿到真实的row
                            row = addRow + r
                            if row > self.rowCount() - 1:
                                # 新增行
                                rowData = [None] * self.columnCount()
                                rowData[c : c + len(ls1[addRow])] = ls1[addRow]
                                self.addRow(row, rowData)
                            else:
                                # 修改行
                                rowData = self.getRowData(row)
                                rowData[c : c + len(ls1[addRow])] = ls1[addRow]
                                self.fillRowData(row, rowData)
                else:
                    # 单个 复制单个单元或值，粘贴到所有选中的单元格中
                    for index in indexes:
                        if self.isFirstColumnUnique and index.column() == 0:
                            # TODO这里暂时禁止复制，后续可继续优化处理
                            continue
                        self.updateCellData(index.row(), index.column(), text)
            else:
                # 直接粘贴
                if self.isFirstColumnUnique:
                    copyData = ls1.copy()
                    tableDict = self.getTableDict()
                    for addIndex in range(len(copyData) - 1, -1, -1):  # 倒序遍历
                        csvRow = copyData[addIndex]
                        if csvRow[0] is not None and str(csvRow[0]) in tableDict:
                            self.updateRowData(tableDict[str(csvRow[0])]["row"], csvRow)
                            del ls1[addIndex]
                    self.addMulitRows(ls1, isResizeRows=True)
                else:
                    self.addMulitRows(ls1, isResizeRows=True)
        except Exception as e:
            print(e)
            return

    def selected_tb_text(self):
        try:
            indexes = self.selectedIndexes()  # 获取表格对象中被选中的数据索引列表
            indexes_dict = {}
            for index in indexes:  # 遍历每个单元格
                row, column = index.row(), index.column()  # 获取单元格的行号，列号
                if row in indexes_dict.keys():
                    indexes_dict[row].append(column)
                else:
                    indexes_dict[row] = [column]
            # 将数据表数据用制表符(\t)和换行符(\n)连接，使其可以复制到excel文件中
            text = ""
            for row, columns in indexes_dict.items():
                row_data = None
                for column in columns:
                    # if column in self.rowSelect:
                    #     wrapWidget = self.cellWidget(row, column)
                    #     wrapLayout = wrapWidget.layout()
                    #     selectBox = wrapLayout.itemAt(0).widget()
                    #     data = selectBox.getValue()
                    # elif column in self.rowMultiSelect:
                    #     wrapWidget = self.cellWidget(row, column)
                    #     data = ','.join(wrapWidget.getValue())
                    # else:
                    data = self.item(row, column).text()

                    if row_data is not None:
                        row_data = row_data + "\t" + data
                    else:
                        row_data = data

                if text:
                    text = text + "\n" + row_data
                else:
                    text = row_data if row_data is not None else ""
            return text
        except BaseException as e:
            print(e)
            return ""

    def selectChanged(self, *args, **kwargs):
        self.select_changed_signal.emit(args)

    def set_column_read_only(self, column):
        if isinstance(column, list):
            self.columnReadOnly = column
        else:
            self.columnReadOnly.append(column)

    # column rules
    def rowSetInt(self, toInt):
        if isinstance(toInt, list):
            self.rowInt = toInt
            for row in toInt:
                self.setItemDelegateForColumn(row, IntValidatorDelegate(self))
        else:
            self.rowInt.append(toInt)
            self.setItemDelegateForColumn(toInt, IntValidatorDelegate(self))

    def rowSetFloat(self, toFloat):
        if isinstance(toFloat, list):
            self.rowFloat = toFloat
            for row in toFloat:
                self.setItemDelegateForColumn(row, FloatValidatorDelegate(self))
        else:
            self.rowFloat.append(toFloat)
            self.setItemDelegateForColumn(toFloat, FloatValidatorDelegate(self))

    def rowSetSelect(self, toSelect, options={}):
        self.selectOptions = options
        if isinstance(toSelect, list):
            self.rowSelect = toSelect
        else:
            self.rowSelect.append(toSelect)

    def rowSetMultiSelect(self, toSelect, options={}):
        self.selectMultiOptions = options
        if isinstance(toSelect, list):
            self.rowMultiSelect = toSelect
        else:
            self.rowMultiSelect.append(toSelect)

    def getRuleValueToStr(self, value, column):
        if column in self.rowFloat:
            return str(TypeConversion.toFloat(value))
        elif column in self.rowInt:
            return str(TypeConversion.toInt(value))
        else:
            return str(value) if value else ""

    def getRuleValue(self, value, column):
        if column in self.rowFloat:
            return TypeConversion.toFloat(value)
        elif column in self.rowInt:
            return TypeConversion.toInt(value)
        else:
            return str(value) if value else ""

    def on_cell_double_clicked(self, row, column):
        self.current_edit_row = row
        self.current_edit_col = column
        if column == 0:
            item = self.item(row, column)
            if item:
                if not (item.flags() & Qt.ItemIsEditable):
                    MBox.warning(self.noEditHint)
        if column in self.rowSelect:
            opt = self.selectOptions[str(column)]
            combo = CustomComboBox(
                options=opt,
                flag=[row, column],
                onChanged=lambda *args, **kwargs: self.selectChanged(
                    self, *args, **kwargs
                ),
            )
            combo.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Expanding)
            combo.popupHidden.connect(partial(self.remove_combo, row=row, col=column))
            item = self.item(row, column)
            if item:
                combo.setValue(item.text())
            self.setCellWidget(row, column, combo)
            combo.showPopup()
        elif column in self.rowMultiSelect:
            opt = copy.deepcopy(self.selectMultiOptions[str(column)])
            multiSelect = CustomCellComboBoxMultiSelectStr(options=opt)
            multiSelect.multiSelectPopupHidden.connect(
                partial(self.remove_combo, row=row, col=column)
            )
            item = self.item(row, column)
            if item:
                multiSelect.setValue(item.text())
            self.setCellWidget(row, column, multiSelect)
            multiSelect.showPopup()

    def remove_combo(self, value, row, col):
        # 赋值给item
        item = self.item(row, col)
        if item is not None:
            if value != "":
                item.setText(value)
        else:
            # 如果单元格没有项，则创建一个新的空项并设置
            if value != "":
                self.setItem(row, col, CustomTableWidgetItem(value))
        # 删除指定单元格中的 QComboBox
        combo = self.cellWidget(row, col)
        if combo:
            combo.deleteLater()  # 安全删除
            self.removeCellWidget(row, col)

    # basic
    # 插入一行，可设置数据
    def addRow(self, row=-1, rowData=[]):
        row_position = row
        if row < 0:
            row_position = self.rowCount()
        self.isAdding = True
        self.insertRow(row_position)
        for column in range(self.columnCount()):
            # if column in self.rowSelect:
            #     opt = self.selectOptions[str(column)]
            # combo = SelectBox(options=opt,  flag=[row_position, column], onChanged = lambda *args, **kwargs: self.selectChanged(
            #         self, *args, **kwargs
            #     ),)
            # combo.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Expanding)
            # combo.setFixedHeight(25)
            # layout = QVBoxLayout()
            # layout.addWidget(combo)
            # cell_widget = QWidget()
            # cell_widget.setLayout(layout)
            # self.setCellWidget(row_position, column, cell_widget)
            # elif column in self.rowMultiSelect:
            #     opt = copy.deepcopy(self.selectMultiOptions[str(column)])
            #     multiSelect = CustomCellComboBoxMultiSelectStr(options=opt)
            #     self.setCellWidget(row_position, column, multiSelect)
            # else:
            item = CustomTableWidgetItem("")
            item.setTextAlignment(Qt.AlignCenter)
            self.setItem(row_position, column, item)
            if column in self.columnReadOnly:
                item.isComplete = True
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)  # 移除可编
                item.setForeground(QColor(255, 255, 255, 128))
        self.fillRowData(row_position, rowData)
        self.isAdding = False

    # 末尾插入多行，并设置数据
    def addMulitRows(self, rowsData=[], isResizeRows=True):
        for rowData in rowsData:
            self.addRow(rowData=rowData)

    # 填充指定行数据
    def fillRowData(self, row, rowData):
        totalColumn = self.columnCount()
        for column, data in enumerate(rowData):
            # item = CustomTableWidgetItem(data)
            # self.setItem(row, column, item)
            if column >= totalColumn:
                break
            # item = self.item(row, column)
            # if column in self.rowSelect:
            #     wrapWidget = self.cellWidget(row, column)
            #     wrapLayout = wrapWidget.layout()
            #     selectBox = wrapLayout.itemAt(0).widget()
            #     selectBox.setValue(self.getRuleValueToStr(data, column))
            # elif column in self.rowMultiSelect:
            #     wrapWidget = self.cellWidget(row, column)
            #     list = data
            #     if isinstance(list, str):
            #         list = list.split(',')
            #     wrapWidget.setValue(list)
            # else:
            item = self.item(row, column)
            if item is None:
                item = CustomTableWidgetItem(self.getRuleValueToStr(data, column))
                self.setItem(row, column, item)
            else:
                if self.flag == "majorCycle" or self.flag == "primaryCycle":
                    if column == 2:
                        item.setText(
                            self.getRuleValueToStr(
                                TypeConversion.roundToString(data, 2), column
                            ),
                            data,
                        )
                    elif column == 4:
                        item.setText(
                            self.getRuleValueToStr(
                                TypeConversion.roundToString(data, 3), column
                            ),
                            data,
                        )
                    elif column == 5:
                        item.setText(
                            self.getRuleValueToStr(
                                TypeConversion.roundToString(data, 3), column
                            ),
                            data,
                        )
                    else:
                        item.setText(self.getRuleValueToStr(data, column))
                elif self.flag == "minorCycle":
                    if column == 4:
                        item.setText(
                            self.getRuleValueToStr(
                                TypeConversion.roundToString(data, 3), column
                            ),
                            data,
                        )
                    elif column == 5:
                        item.setText(
                            self.getRuleValueToStr(
                                TypeConversion.roundToString(data, 3), column
                            ),
                            data,
                        )
                    else:
                        item.setText(self.getRuleValueToStr(data, column))
                else:
                    item.setText(self.getRuleValueToStr(data, column))

    # 更新指定行的数据
    def updateRowData(self, row, rowData):
        for col in range(self.columnCount()):
            if len(rowData) > col:
                self.updateCellData(row, col, rowData[col])

    # 更新指定单元格的数据
    def updateCellData(self, row, col, value):
        item = self.item(row, col)
        # if col in self.rowSelect:
        #     wrapWidget = self.cellWidget(row, col)
        #     wrapLayout = wrapWidget.layout()
        #     selectBox = wrapLayout.itemAt(0).widget()
        #     selectBox.setValue(self.getRuleValueToStr(value, col))
        # elif col in self.rowMultiSelect:
        #     wrapWidget = self.cellWidget(row, col)
        #     list = value
        #     if isinstance(list, str):
        #         list = list.split(',')
        #     wrapWidget.setValue(list)
        # else:
        if item is None:
            item = CustomTableWidgetItem()
            self.setItem(row, col, item)
        if item.flags() & Qt.ItemIsEditable:
            item.setText(self.getRuleValueToStr(value, col))

    # 设置指定行单元格内容居中显示，适用于新增行
    def cellSetCenter(self, row):
        for column in range(self.columnCount()):
            item = CustomTableWidgetItem()
            item.setTextAlignment(Qt.AlignCenter)
            self.setItem(row, column, item)

    # 获取当前选中行的最后一行行号
    def selectedLastRow(self):
        last_row_number = -1
        selected_indexes = self.selectedIndexes()
        if selected_indexes:
            # 获取所有选中行的行号
            rows = [index.row() for index in selected_indexes]
            # 找到最后一行的行号
            last_row_number = max(rows)
        return last_row_number

    def getRowData(self, row):
        list = []
        if row > self.rowCount() - 1:
            return None
        for col in range(self.columnCount()):
            # if col in self.rowSelect:
            #     wrapWidget = self.cellWidget(row, col)
            #     wrapLayout = wrapWidget.layout()
            #     selectBox = wrapLayout.itemAt(0).widget()
            #     list.append(selectBox.getValue())
            # elif col in self.rowMultiSelect:
            #     wrapWidget = self.cellWidget(row, col)
            #     list.append(wrapWidget.getValue())
            # else:
            item = self.item(row, col)
            if item is not None:
                if item.isComplete:
                    list.append(self.getRuleValue(item.getCompleteValue(), col))
                else:
                    list.append(self.getRuleValue(item.text(), col))
            else:
                list.append(None)
        return list

    def getColumnData(self, col):
        list = []
        if col > self.columnCount() - 1:
            return None
        for row in range(self.rowCount()):
            item = self.item(row, col)
            if item is not None:
                if item.isComplete:
                    list.append(self.getRuleValue(item.getCompleteValue(), col))
                else:
                    list.append(self.getRuleValue(item.text(), col))
            else:
                list.append(None)
        return list

    def getTableData(self):
        data = []
        for row in range(self.rowCount()):
            data.append(self.getRowData(row))
        return data

    def getTableDict(self):
        dict = {}
        for row in range(self.rowCount()):
            rowData = self.getRowData(row)
            if rowData:
                if rowData[0] == "" or rowData[0] is None:
                    continue
                dict[str(rowData[0])] = {"content": rowData, "row": row}
        return dict

    def getTableDictFirstNoNull(self):
        dict = {}
        for row in range(self.rowCount()):
            rowData = self.getRowData(row)
            if rowData:
                # 判断是否为空，空返回int
                if rowData[0] == "" or rowData[0] is None:
                    return row + 1
                # 判断是否重复，重复返回str
                if str(rowData[0]) in dict:
                    return str(row + 1)
                dict[str(rowData[0])] = rowData
        return dict

    def setAllColumnWidth(self, width):
        for column in range(self.columnCount()):
            self.setColumnWidth(column, width)

    # 清空表格数据
    def clearRow(self, row=-1):
        if row >= 0:
            column_count = self.columnCount()
            # 遍历每一列
            for column in range(column_count):
                # 获取当前单元格的项
                item = self.item(row, column)
                if item is not None:
                    # 将单元格内容设置为空字符串
                    item.setText("")
                else:
                    # 如果单元格没有项，则创建一个新的空项并设置
                    self.setItem(row, column, CustomTableWidgetItem(""))
        else:
            if self.hasNoEditCell and self.isHandleDel:
                isDel = MBox.confirm(
                    "当前选中行包含被使用的材料，被使用的材料无法删除，是否继续?",
                )
                if isDel:
                    rowCount = self.rowCount()
                    for row in range(rowCount - 1, -1, -1):
                        item = self.item(row, 0)
                        if item.flags() & Qt.ItemIsEditable:
                            self.removeRow(row)
                        rowCount = rowCount - 1
            else:
                isDel = MBox.confirm(
                    "是否确认清空表格数据?",
                )
                if isDel:
                    self.setRowCount(0)

    def value_is_duplicate(self, row=0, curItem=None, hint="名称重复！"):
        isDeplicate = False
        if curItem is None or curItem.text().strip() == "":
            return
        for i in range(self.rowCount()):
            item = self.item(i, row)
            if item is not None and curItem is not item:
                if curItem.text().strip() == item.text().strip():
                    isDeplicate = True
                    curItem.setText("")
                    continue
        if isDeplicate:
            MBox.warning(hint)
